#include <glog/logging.h>
#include <memory>
#include <sstream>


// 日志
#define LOG_STRING_STREAM(level, ...)                \
        do{                                         \
            std::stringstream ss = concat_string_stream(__VA_ARGS__); ;                   \
            LOG(level) << ss.str();                 \
        }while(0)                                   \


#define LOG_INFO(...) LOG_STRING_STREAM(INFO, __VA_ARGS__)
#define LOG_WARNING(...) LOG_STRING_STREAM(WARNING, __VA_ARGS__)
#define LOG_ERROR(...) LOG_STRING_STREAM(ERROR, __VA_ARGS__)
#define LOG_FATAL(...) LOG_STRING_STREAM(FATAL, __VA_ARGS__)


#define THROW_EXCEPTION(EXCEPTION, ...)                                 \
    {                                                                   \
        std::stringstream ss = concat_string_stream(__VA_ARGS__);       \
        throw EXCEPTION(ss.str());                                      \
    }

#define THROW_RUNTIME_ERROR(msg) THROW_EXCEPTION(std::runtime_error, msg)


template<typename T>
std::stringstream concat_string_stream(const T& first) {
    std::stringstream ss;
    ss << first;
    return ss;
}

template<typename T, typename... Args>
std::stringstream concat_string_stream(const T& first, Args... args) {
    std::stringstream ss;
    ss << first << " ";
    if constexpr (sizeof...(args) > 0) { // 使用 if constexpr 来处理递归情况
        ss << concat_string_stream(args...).str();
    }
    return ss;
}


namespace log {

enum class LogLevel {
    Fatal,
    Error,
    Warning,
    Info,
    Debug,
    Trace
};

class Logger {
public:
    std::shared_ptr<Logger> getInstance();

    void setLogLevel(LogLevel level);

    Logger();

    ~Logger();
    
    std::shared_ptr<Logger> _instance = nullptr;

    Logger(const Logger&) = delete;

    Logger& operator=(const Logger&) = delete;

};

}  // namespace log
